using System;
using System.Collections.Generic;
using System.IO;
using System.Globalization;

namespace LaplaceMeshDeformer
{
    /// <summary>
    /// 三角网格IO类
    /// 提供网格文件的读写功能
    /// </summary>
    public static class TriMeshIO
    {
        /// <summary>
        /// 从文件加载网格
        /// </summary>
        /// <param name="filename">文件路径</param>
        /// <returns>加载的网格，失败返回null</returns>
        public static TriMesh LoadMesh(string filename)
        {
            if (!File.Exists(filename))
            {
                throw new FileNotFoundException($"文件不存在: {filename}");
            }

            string extension = Path.GetExtension(filename).ToLower();
            switch (extension)
            {
                case ".obj":
                    return LoadOBJ(filename);
                default:
                    throw new NotSupportedException($"不支持的文件格式: {extension}");
            }
        }

        /// <summary>
        /// 从OBJ文件加载网格
        /// </summary>
        /// <param name="filename">OBJ文件路径</param>
        /// <returns>加载的网格</returns>
        private static TriMesh LoadOBJ(string filename)
        {
            TriMesh mesh = new TriMesh();
            
            // 使用InvariantCulture确保正确解析浮点数
            CultureInfo ci = CultureInfo.InvariantCulture;
            
            string[] lines = File.ReadAllLines(filename);
            List<Vector3D> positions = new List<Vector3D>();
            List<Vector3D> normals = new List<Vector3D>();
            
            // 首先读取顶点和法线数据
            foreach (string line in lines)
            {
                if (string.IsNullOrWhiteSpace(line) || line.StartsWith("#"))
                    continue;
                
                string[] parts = line.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
                if (parts.Length == 0)
                    continue;
                
                if (parts[0] == "v" && parts.Length >= 4)
                {
                    // 顶点位置
                    double x = double.Parse(parts[1], ci);
                    double y = double.Parse(parts[2], ci);
                    double z = double.Parse(parts[3], ci);
                    positions.Add(new Vector3D(x, y, z));
                }
                else if (parts[0] == "vn" && parts.Length >= 4)
                {
                    // 顶点法线
                    double x = double.Parse(parts[1], ci);
                    double y = double.Parse(parts[2], ci);
                    double z = double.Parse(parts[3], ci);
                    normals.Add(new Vector3D(x, y, z));
                }
            }
            
            // 添加顶点到网格
            foreach (Vector3D pos in positions)
            {
                mesh.AddVertex(pos);
            }
            
            // 读取面数据并添加到网格
            foreach (string line in lines)
            {
                if (string.IsNullOrWhiteSpace(line) || line.StartsWith("#"))
                    continue;
                
                string[] parts = line.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
                if (parts.Length == 0)
                    continue;
                
                if (parts[0] == "f")
                {
                    List<int> faceVertices = new List<int>();
                    
                    // 解析面的顶点索引
                    for (int i = 1; i < parts.Length; i++)
                    {
                        string[] indices = parts[i].Split('/');
                        
                        if (indices.Length >= 1 && !string.IsNullOrEmpty(indices[0]))
                        {
                            // OBJ索引从1开始，需要减1
                            int vertIndex = int.Parse(indices[0]) - 1;
                            faceVertices.Add(vertIndex);
                        }
                    }
                    
                    // 如果面有3个或更多顶点，添加到网格
                    if (faceVertices.Count >= 3)
                    {
                        // 三角化多边形（如果需要）
                        for (int i = 0; i < faceVertices.Count - 2; i++)
                        {
                            List<int> triangleFace = new List<int>
                            {
                                faceVertices[0],
                                faceVertices[i + 1],
                                faceVertices[i + 2]
                            };
                            mesh.AddFace(triangleFace);
                        }
                    }
                }
            }
            
            // 构建网格连接关系
            mesh.BuildConnectivity();
            
            // 计算法线
            TriMeshUtil.ComputeFaceNormals(mesh);
            TriMeshUtil.ComputeVertexNormals(mesh);
            
            return mesh;
        }

        /// <summary>
        /// 保存网格到文件
        /// </summary>
        /// <param name="mesh">要保存的网格</param>
        /// <param name="filename">文件路径</param>
        public static void SaveMesh(TriMesh mesh, string filename)
        {
            string extension = Path.GetExtension(filename).ToLower();
            
            switch (extension)
            {
                case ".obj":
                    SaveOBJ(mesh, filename);
                    break;
                default:
                    throw new NotSupportedException($"不支持的文件格式: {extension}");
            }
        }

        /// <summary>
        /// 保存网格到OBJ文件
        /// </summary>
        /// <param name="mesh">要保存的网格</param>
        /// <param name="filename">OBJ文件路径</param>
        private static void SaveOBJ(TriMesh mesh, string filename)
        {
            using (StreamWriter writer = new StreamWriter(filename))
            {
                // 写入文件头
                writer.WriteLine("# OBJ文件由LaplaceMeshDeformer生成");
                writer.WriteLine("# 顶点数: " + mesh.VertexCount);
                writer.WriteLine("# 面片数: " + mesh.FaceCount);
                writer.WriteLine();
                
                // 写入顶点
                for (int i = 0; i < mesh.VertexCount; i++)
                {
                    TriMesh.Vertex vertex = mesh.GetVertex(i);
                    writer.WriteLine(string.Format(CultureInfo.InvariantCulture, 
                        "v {0} {1} {2}", 
                        vertex.Position.X, 
                        vertex.Position.Y, 
                        vertex.Position.Z));
                }
                
                writer.WriteLine();
                
                // 写入法线
                for (int i = 0; i < mesh.VertexCount; i++)
                {
                    TriMesh.Vertex vertex = mesh.GetVertex(i);
                    writer.WriteLine(string.Format(CultureInfo.InvariantCulture, 
                        "vn {0} {1} {2}", 
                        vertex.Normal.X, 
                        vertex.Normal.Y, 
                        vertex.Normal.Z));
                }
                
                writer.WriteLine();
                
                // 写入面，OBJ索引从1开始
                for (int i = 0; i < mesh.FaceCount; i++)
                {
                    TriMesh.Face face = mesh.GetFace(i);
                    writer.WriteLine(string.Format("f {0}//{0} {1}//{1} {2}//{2}", 
                        face.GetVertexIndex(0) + 1, 
                        face.GetVertexIndex(1) + 1, 
                        face.GetVertexIndex(2) + 1));
                }
            }
        }

        /// <summary>
        /// 深度克隆网格
        /// </summary>
        /// <param name="source">源网格</param>
        /// <returns>克隆后的网格</returns>
        public static TriMesh Clone(TriMesh source)
        {
            TriMesh mesh = new TriMesh();
            
            // 复制顶点
            for (int i = 0; i < source.VertexCount; i++)
            {
                TriMesh.Vertex srcVertex = source.GetVertex(i);
                Vector3D position = new Vector3D(srcVertex.Position);
                int index = mesh.AddVertex(position);
                
                // 复制法线
                mesh.GetVertex(index).Normal = new Vector3D(srcVertex.Normal);
                
                // 复制选择状态
                mesh.GetVertex(index).Selected = srcVertex.Selected;
            }
            
            // 复制面
            for (int i = 0; i < source.FaceCount; i++)
            {
                TriMesh.Face srcFace = source.GetFace(i);
                List<int> vertexIndices = new List<int>();
                
                for (int j = 0; j < 3; j++)
                {
                    vertexIndices.Add(srcFace.GetVertexIndex(j));
                }
                
                mesh.AddFace(vertexIndices);
            }
            
            // 构建连接关系
            mesh.BuildConnectivity();
            
            return mesh;
        }

        /// <summary>
        /// 浅克隆网格
        /// </summary>
        /// <param name="source">源网格</param>
        /// <returns>克隆后的网格</returns>
        public static TriMesh Copy(TriMesh source)
        {
            return Clone(source);
        }
    }
} 